package com.huoshan.im.server;

import com.huoshan.im.server.action.*;
import com.huoshan.im.server.config.ConfigHolder;
import com.huoshan.im.server.config.properties.SettingConfig;
import com.huoshan.im.server.filter.AuthorizeFilter;
import com.huoshan.im.server.listener.ChannelListener;
import com.huoshan.im.server.listener.SessionListener;
import com.huoshan.im.server.messaging.MessageEncryptor;
import com.huoshan.im.server.messaging.MessageId;
import com.huoshan.im.server.proxy.ActionAutoInjectProxy;
import com.huoshan.im.server.service.ServerService;
import lombok.extern.slf4j.Slf4j;
import online.chazi.bootplus.commons.utils.IfUtils;
import online.chazi.netkit.NetkitContext;
import online.chazi.netkit.action.DoNotingAction;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 注意：特定针对云主机进行编码！
 * （1）不支持docker容器化运行
 * （2）如果是物理机运行及对外网提供服务，需要指定外网ip
 * （3）支持多张网卡的高io云主机机型
 * Created by 火山九日 on 2020-04-25 17:40
 */
@Slf4j
public abstract class BaseChatServer {

    @Autowired
    protected SettingConfig settingConfig;
    @Autowired
    protected ServerService serverService;
    @Autowired
    protected AuthorizeFilter authorizeFilter;
    @Autowired
    protected ChannelListener channelListener;
    @Autowired
    protected SessionListener sessionListener;
    @Autowired
    protected MessageEncryptor messageEncryptor;
    @Autowired
    protected ActionAutoInjectProxy actionAutoInjectProxy;

    protected void init(NetkitContext context) {
        context.setSessionTimeout(Duration.ofSeconds(settingConfig.getServer().getTimeoutSeconds()));
        context.addActionFilter(authorizeFilter);
        context.setChanelListener(channelListener);
        context.setSessionListener(sessionListener);
        context.setMessageEncrypt(messageEncryptor);
        context.setInjectProxy(actionAutoInjectProxy); //非spring管理的类注入代理
        context.setUsingActionCached(settingConfig.getCache());
        registerActions(context);
    }

    protected void registerActions(NetkitContext context) {

        //默认给一个，不然匹配不到的时候，不会触发 filter
        context.setNotFoundAction(new DoNotingAction());
        // 通用action
        context.registerAction(MessageId.MESSAGE_FROM_CLIENT.id, TransferMessageAction.class);
        context.registerAction(MessageId.MESSAGE_FROM_REPEATER.id, ReplyClientMessageAction.class);

        //心跳消息
        context.registerAction(MessageId.NORMAL_HEARTBEAT.id, HeartbeatAction.class);
        //repeater的登录消息
        context.registerAction(MessageId.SYS_LOGIN.id, SysLoginAction.class);

        //处理登录action
        context.registerAction(MessageId.NORMAL_LOGIN.id, LoginAction.class);

    }

    protected void cacheServer() {
        List<String> cacheHostList = new ArrayList<>();
        if ("0.0.0.0".equals(settingConfig.getServer().getHost())) {
            //多网卡，不支持docker容器化
            List<String> hosts = IfUtils.getLocalHosts();
            for (String host : hosts) {
                if ("127.0.0.1".equals(host) || host.endsWith(".1")) continue;
                cacheHostList.add(host);
            }
        } else {
            cacheHostList.add(settingConfig.getServer().getHost());
        }
        ConfigHolder.setLocalHostList(cacheHostList);
        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
            try {
                serverService.cacheServerList();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }, 5, 60, TimeUnit.SECONDS);
    }
}
